/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年5月23日
 */
package com.massyframework.beanskin;

import java.util.List;
import java.util.function.Predicate;

import com.massyframework.beanskin.fragment.Fragment;
import com.massyframework.beanskin.util.version.Version;

/**
 * 模块资源库提供对所有在运行模块的管理，支持按编号、模块类型、模块标识符查找和定位模块。
 * @author huangkh
 *
 */
public interface ModuleRepository {
	
	/**
	 * 添加事件监听器
	 * @param listener {@link ModuleListener}
	 */
	void addListener(ModuleListener listener);

	/**
	 * 按{@code id}查找模块
	 * @param id {@link int},模块编号
	 * @return {@link Module},可能返回null.
	 */
	Module<?> findModuleById(int id);
		
	/**
	 * 按{@code id}查找模块,并按{@code requiredType}返回.
	 * @param id {@link int},模块编号
	 * @return {@link Module}, 可能返回null.
	 */
	default <T extends Module<?>> T findModuleById(int id, Class<T> requireType) {
		Module<?> result = this.findModuleById(id);
		if (result == null) return null;
		return requireType.isAssignableFrom(result.getClass()) ? requireType.cast(result) : null;
	}
	
	/**
	 * 按{@code identifier}查找模块
	 * @param identifier {@link ModuleIdentifier}
	 * @return {@link Module}, 无对应模块可以返回null.
	 */
	Module<?> findModuleByIdentifier(ModuleIdentifier identifier);
		
	/**
	 * 按组编号、模块编号和版本查找模块
	 * @param groupId {@link String},组编号
	 * @param moduleId {@link String},模块编号
	 * @param version {@link String},版本
	 * @return {@link Module},可能返回null.
	 */
	default Module<?> findModuleByIdentifier(String groupId, String moduleId, String version){
		ModuleIdentifier identifier =
				SimpleModuleIdentifier.newBuilder()
					.groupId(groupId)
					.moduleId(moduleId)
					.version(Version.parseVersion(version))
					.build();
		return this.findModuleByIdentifier(identifier);
	}
	
	/**
	 * 按组编号、模块编号和版本查找模块
	 * @param groupId {@link String},组编号
	 * @param moduleId {@link String},模块编号
	 * @param version {@link Version},版本
	 * @return {@link Module},可能返回null.
	 */
	default Module<?> findModuleByIdentifier(String groupId, String moduleId, Version version){
		ModuleIdentifier identifier =
				SimpleModuleIdentifier.newBuilder()
					.groupId(groupId)
					.moduleId(moduleId)
					.version(version)
					.build();
		return this.findModuleByIdentifier(identifier);
	}
	
		
	/**
	 * 按{@code identifier}查找模块，并按指定类型返回
	 * @param <T>
	 * @param identifier {@link ModuleIdentifier},模块标识符
	 * @param requireType {@link Class}，要求返回的类型
	 * @return {@link T},无对应模块可以返回null.
	 */
	default <T extends Module<?>> T findModuleByIdentifier(ModuleIdentifier identifier, Class<T> requireType) {
		Module<?> result = this.findModuleByIdentifier(identifier);
		if (result == null) return null;
		return requireType.isAssignableFrom(result.getClass()) ? requireType.cast(result) : null;
	}
	
	/**
	 * 按{@code filter}查找首个满足条件的模块
	 * @param filter {@link filter}, 过滤条件
	 * @return {@link Module},无满足条件情况下可返回null.
	 */
	Module<?> findByFilter(Predicate<Module<?>> filter);
	
	/**
	 * 按{@code filter}查找首个满足条件的模块，并按{@code requireType}返回
	 * @param <T>
	 * @param filter {@link Predicate},过滤条件
	 * @param requireType {@link Class},类型
	 * @return {@link T},无满足条件情况下可返回null.
	 */
	default <T extends Module<?>> T findByFilter(Predicate<T> filter, Class<T> requireType) {
		Predicate<Module<?>> newFilter = module-> {
			if (requireType.isAssignableFrom(module.getClass())) {
				return filter.test(requireType.cast(module));
			}
			return false;
		};
				
		Module<?> result = this.findByFilter(newFilter);
		return result == null ? null : requireType.cast(result);
	}
	
	/**
	 * 查找最优版本的模块
	 * @param require {@link RequireLibraryDescriptor}, 依赖模块描述
	 * @return {@link Module},如果无满足条件情况可返回null.
	 */
	Module<?> findModuleWithOptimal(RequireLibraryDescriptor require);
	
	
	/**
	 * 所有模块
	 * @return {@link List}
	 */
	List<Module<?>> getModules();
	
	/**
	 * 满足{@code filter}条件的模块
	 * @param filter {@link Predicate},过滤条件
	 * @return {@link List}
	 */
	List<Module<?>> getModules(Predicate<Module<?>> filter);
	
	/**
	 * 满足{@code filter}条件的模块
	 * @param <T>
	 * @param filter {@link Predicate},过滤条件
	 * @param requireType {@link Class},要求返回的类型
	 * @return {@link List}
	 */
	<T extends Module<?>> List<T> getModules(Predicate<T> filter, Class<T> requireType);
	
	/**
	 * 移除事件监听器
	 * @param listener {@link ModuleListener},监听器
	 */
	void removeListener(ModuleListener listener);
	
	/**
	 * 记录总数
	 * @return {@link int}
	 */
	int size();
	
	/**
	 * 卸载片段
	 * @param fragment {@link Fragment}
	 * @return {@link boolean},返回{@code true}表示卸载成功，否则返回{@code false}
	 */
	boolean uninstall(Fragment fragment);
}
